home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1997 / MacHack 1997.toast / Hacks / Hacks ’97 / Animated Icons / Source / AnimatedIcons.cp < prev    next >
Encoding:
Text File  |  1997-06-28  |  17.6 KB  |  645 lines  |  [TEXT/CWIE]

  1. #include "AnimatedIcons.h"
  2. #include "LArrayIterator.h"
  3. #include "IconSuitePatches.h"
  4. #include <limits.h>
  5. #include <speech.h>
  6.  
  7. #ifndef BUILDINGINIT
  8. #include <iostream.h>
  9. #endif
  10.  
  11. #include <stdio.h>
  12.  
  13. int     vdprintf( const char * format, va_list arg);
  14. int    dprintf(const char * format, ...);
  15.  
  16. //    ============================================================================================
  17.  
  18. unsigned long gNextTickToCheckAnimations = 0;
  19.  
  20. //    ============================================================================================
  21.  
  22. LArray*    gIconsToAnimate = nil;
  23. LArray*    gIconsOnScreen = nil;
  24.  
  25. //    ============================================================================================
  26.  
  27.  
  28. AnimatedIcon::AnimatedIcon ( void* iconSuiteToReplace ) :
  29.     mIconSuiteWeAreReplacing ( iconSuiteToReplace )
  30. {    
  31.     #ifndef BUILDINGINIT
  32.     cout << "AnimatedIcon::AnimatedIcon() @ " << (void*) this << endl;
  33.     #endif
  34.     
  35.     if ( gIconsToAnimate )
  36.         gIconsToAnimate->InsertItemsAt ( 1, LArray::index_Last, & this, sizeof( this ) ); 
  37. }
  38.  
  39. AnimatedIcon::~AnimatedIcon ( )
  40. {
  41.     #ifndef BUILDINGINIT
  42.     cout << "AnimatedIcon::~AnimatedIcon() @" << (void*) this << endl;
  43.     #endif
  44.  
  45.     if ( gIconsToAnimate )
  46.         gIconsToAnimate->Remove ( & this, sizeof( this ) );
  47. }
  48.  
  49. AnimatedIcon* AnimatedIcon::GetAnimatedIconForIconSuite ( void* iconSuite )
  50. {    AnimatedIcon* animatedIcon = nil;
  51.  
  52.     for ( LArrayIterator iter ( *gIconsToAnimate ); iter.Next( & animatedIcon ); )
  53.         if ( animatedIcon && animatedIcon->mIconSuiteWeAreReplacing == iconSuite )
  54.             return animatedIcon;
  55.  
  56.     return nil;
  57. }
  58.  
  59. //    ============================================================================================
  60.  
  61. AnimatedIconOnScreen::AnimatedIconOnScreen ( AnimatedIcon* animatedIcon, GrafPtr port, const Rect* rect, IconAlignmentType align, IconTransformType transform ) :
  62.     mAnimatedIcon ( animatedIcon ),
  63.     mPort ( port ),
  64.     mRect ( *rect ),
  65.     mAlign ( align ),
  66.     mTransform ( transform ),
  67.     mNextAnimationTick ( TickCount() ),
  68.     mInvalidatedCount ( 0 ),
  69.     mBitMap ( nil )
  70. {
  71.     if ( gIconsOnScreen )
  72.         gIconsOnScreen->InsertItemsAt ( 1, LArray::index_Last, & this, sizeof( this ) );
  73. }
  74.  
  75. AnimatedIconOnScreen::~AnimatedIconOnScreen ( )
  76. {
  77.     if ( gIconsOnScreen )
  78.         gIconsOnScreen->Remove ( & this, sizeof( this ) );
  79. }
  80.  
  81. AnimatedIconOnScreen* AnimatedIconOnScreen::GetAnimatedIconOnScreen ( GrafPtr inPort, const Rect& r, void* iconSuiteH )
  82. {    AnimatedIconOnScreen* animatedIcon = nil;
  83.  
  84.     for ( LArrayIterator iter ( *gIconsOnScreen ); iter.Next( & animatedIcon ); )
  85.         if ( animatedIcon && animatedIcon->mAnimatedIcon && animatedIcon->mAnimatedIcon->GetIconSuiteThisReplaces() == iconSuiteH && 
  86.                 ( animatedIcon->mPort == inPort ) &&
  87.                 * (long*) & animatedIcon->mRect.top == * (long*) & r.top &&
  88.                 * (long*) & animatedIcon->mRect.bottom == * (long*) & r.bottom )
  89.             return animatedIcon;
  90.  
  91.     return nil;
  92. }
  93.  
  94. //    ============================================================================================
  95.  
  96. FrameAnimatedIcon::FrameAnimatedIcon ( void* iconSuiteToReplace, FrameAnimatedIconResourceHandle aicnHandle ) :
  97.     AnimatedIcon ( iconSuiteToReplace )
  98. {    
  99.     if ( (**aicnHandle).signature == 'KSDC' && (**aicnHandle).version == 1 )
  100.     {
  101.         mTicksPerAnimationCycle = (**aicnHandle).ticksPerAnimationCycle;
  102.         
  103.         mCountOfAnimatedIcons = (**aicnHandle).countOfAnimatedIcons;
  104.         
  105.         for ( unsigned short i = 0; i < mCountOfAnimatedIcons; i ++ )
  106.         {
  107.             CallGetIconSuite ( & mAnimatedIcons[i], (**aicnHandle).icons[i], kSelectorAllAvailableData );    
  108.             ForEachIconDo ( mAnimatedIcons[i], svAllAvailableData, DetachIconResource, this );
  109.         }
  110.     }
  111. }
  112.  
  113. //    ============================================================================================
  114.  
  115. FrameAnimatedIcon::~FrameAnimatedIcon ( )
  116. {
  117.     for ( unsigned short i = 0; i < mCountOfAnimatedIcons; i ++ )
  118.         if ( mAnimatedIcons[i] )
  119.             CallDisposeIconSuite ( mAnimatedIcons[i], true );
  120. }
  121.  
  122. //    ============================================================================================
  123.  
  124. pascal OSErr FrameAnimatedIcon::DetachIconResource ( OSType resType, Handle* iconHandle, void* yourDataPtr )
  125. {
  126.     #pragma unused(resType,yourDataPtr)
  127.     
  128.     if ( *iconHandle )
  129.         DetachResource ( *iconHandle );
  130.     
  131.     return noErr;
  132. }
  133.  
  134. //    ============================================================================================
  135.  
  136. FrameAnimatedIconOnScreen::FrameAnimatedIconOnScreen (  AnimatedIcon* animatedIcon, GrafPtr port, const Rect* rect, IconAlignmentType align, IconTransformType transform ) :
  137.     AnimatedIconOnScreen ( animatedIcon, port, rect, align, transform ),
  138.     mTicksPerAnimationCycle ( ( (FrameAnimatedIcon*) animatedIcon)->mTicksPerAnimationCycle ),
  139.     mCountOfAnimatedIcons ( ( (FrameAnimatedIcon*) animatedIcon)->mCountOfAnimatedIcons )
  140. {
  141. }
  142.  
  143. FrameAnimatedIconOnScreen::~FrameAnimatedIconOnScreen ( )
  144. {
  145. }
  146.  
  147. void FrameAnimatedIconOnScreen::Advance ( )
  148. {
  149.     if ( mNextAnimationTick )
  150.     {
  151.         mFrame ++;
  152.         
  153.         if ( mFrame >= GetFrameCount() )
  154.             mFrame = 0;
  155.  
  156.         mNextAnimationTick = TickCount() + GetTicksPerFrame();
  157.     }
  158. }
  159.  
  160. OSErr FrameAnimatedIconOnScreen::Draw (  const Rect* rect, IconAlignmentType align, IconTransformType transform  )
  161. {
  162.     mInvalidatedCount = 0;
  163.     return CallPlotIconSuite ( rect, align, transform, GetFrameIconSuiteHandle( mFrame ) );
  164. }
  165.  
  166. unsigned long FrameAnimatedIconOnScreen::Idle ( )
  167. {
  168.     Draw ( & GetRect(), GetAlign(), GetTransform() );
  169.  
  170.     return GetTicksPerFrame();
  171. }
  172.  
  173. //    ============================================================================================
  174.  
  175. QuicktimeMovieAnimatedIcon::QuicktimeMovieAnimatedIcon ( void* iconSuiteToReplace, QuicktimeMovieAnimatedIconResourceHandle movInfoH ,const FSSpec* spec, short movieResID  ) :
  176.     AnimatedIcon ( iconSuiteToReplace ),
  177.     mMovie ( 0 ),
  178.     mMovieResFileNum ( 0 )
  179. {    OSErr err = -1;
  180.     if ( IsQuicktimeAvailable() )
  181.     {
  182.         if ( (**movInfoH).signature == 'KSDC' && (**movInfoH).version == 1 )
  183.         {
  184.  
  185.             mMovieFlags = (**movInfoH).flags;
  186.             
  187.             
  188.             if ( spec )
  189.             {    
  190.                 err = OpenMovieFile ( spec, & mMovieResFileNum, fsRdPerm );
  191.             
  192.                 if ( err == noErr )
  193.                     err = NewMovieFromFile ( & mMovie, mMovieResFileNum, & movieResID, nil, newMovieActive | newMovieDontAskUnresolvedDataRefs, nil );
  194.             }
  195.                 
  196.             #ifndef BUILDINGINIT
  197.             if ( err )
  198.             {    FSSpec spec;
  199.                 short savedResFile = CurResFile();
  200.             
  201.                 err = FSMakeFSSpec ( 0, 0, "\pQuickTime Logo Movie Test", & spec );
  202.                 if ( err == noErr )
  203.                     err = OpenMovieFile( & spec, & mMovieResFileNum, fsRdPerm );
  204.                 
  205.                 if ( err == noErr )
  206.                     err = NewMovieFromFile ( & mMovie, mMovieResFileNum, & movieResID, nil, newMovieActive | newMovieDontAskUnresolvedDataRefs, nil );
  207.                 
  208.                 UseResFile ( savedResFile );
  209.             }
  210.             #endif
  211.             
  212.             if ( err )
  213.                 mMovie = 0;
  214.         }
  215.     }
  216. }
  217.  
  218. QuicktimeMovieAnimatedIcon::~QuicktimeMovieAnimatedIcon ()
  219. {
  220.     if ( mMovie )
  221.         DisposeMovie ( mMovie );
  222.     
  223.     if ( mMovieResFileNum )
  224.         CloseMovieFile ( mMovieResFileNum );
  225. }
  226.  
  227. Boolean QuicktimeMovieAnimatedIcon::sEnterMoviesCalledByUs = false;
  228. Boolean QuicktimeMovieAnimatedIcon::sQuickTimeAvailableAndInitialized = false;
  229.  
  230. Boolean QuicktimeMovieAnimatedIcon::IsQuicktimeAvailable()
  231. {    
  232.     if ( ! sEnterMoviesCalledByUs )
  233.     {    long quicktimeGestaltValue;
  234.     
  235.         if ( Gestalt ( gestaltQuickTime, & quicktimeGestaltValue ) == noErr )
  236.         {        
  237.             sQuickTimeAvailableAndInitialized = EnterMovies () == noErr;
  238.         }
  239.         
  240.         sEnterMoviesCalledByUs = true;
  241.     }
  242.  
  243.     return sQuickTimeAvailableAndInitialized;    
  244. }
  245.  
  246. //    ============================================================================================
  247.  
  248. QuicktimeMovieAnimatedIconOnScreen::QuicktimeMovieAnimatedIconOnScreen (  AnimatedIcon* animatedIcon, GrafPtr port, const Rect* rect, IconAlignmentType align, IconTransformType transform ) :
  249.     AnimatedIconOnScreen ( animatedIcon, port, rect, align, transform )
  250. {    Movie movie = GetParent()->mMovie;
  251.  
  252.     if ( movie )
  253.     {    
  254.         SetPort ( mPort );
  255.  
  256.         SetRect ( *rect );
  257.  
  258.         if (GetParent()->mMovieFlags & kPlaySound)
  259.             SetMovieVolume ( movie, kFullVolume );
  260.         else
  261.             SetMovieVolume ( movie, kNoVolume );
  262.             
  263.         StartMovie ( movie );
  264.     }
  265. }
  266.  
  267. OSErr QuicktimeMovieAnimatedIconOnScreen::Draw ( const Rect* rect, IconAlignmentType align, IconTransformType transform )
  268. {    
  269.     #pragma unused(rect,align,transform)
  270.     mInvalidatedCount = 0;
  271.     return UpdateMovie ( GetParent()->mMovie );
  272. }
  273.  
  274. unsigned long QuicktimeMovieAnimatedIconOnScreen::Idle ()
  275. {    Movie movie = GetParent()->mMovie;
  276.  
  277.     MoviesTask ( movie, 0 );
  278.     
  279.     if ( IsMovieDone ( movie ) )
  280.         GoToBeginningOfMovie ( movie );
  281.         
  282.     return 0;
  283. }
  284.  
  285. void QuicktimeMovieAnimatedIconOnScreen::SetRect ( const Rect& rect )
  286. {    
  287.     if ( GetParent() )
  288.     {    Rect myRect;
  289.         Movie movie = GetParent()->mMovie;
  290.     
  291.         switch (GetParent()->mMovieFlags & kRectMask)
  292.         {
  293.             case kIconsRect:
  294.                 SetMovieBox ( movie, & rect );
  295.                 break;
  296.                 
  297.             case kParentRect:
  298.                 GetMovieBox ( movie, & myRect);
  299.                 OffsetRect(&myRect,
  300.                            ((rect.left + rect.right)>>1) - ((myRect.left + myRect.right)>>1),
  301.                            rect.bottom - myRect.bottom);
  302.                 SetMovieBox ( movie, &myRect );
  303.                 break;
  304.                 
  305.             case kDontDraw:
  306.                 {
  307.                     RgnHandle theClip = NewRgn ();
  308.                     SetMovieClipRgn ( movie, theClip);
  309.                     DisposeRgn (theClip);
  310.                 }
  311.                 break;
  312.                 
  313.             case kSpareRectMode:
  314.                 SetMovieBox ( movie, & rect );
  315.                 break;
  316.         }
  317.     }
  318. }
  319.  
  320. //    ============================================================================================
  321.  
  322. void QuicktimeMovieAnimatedIconOnScreen::SetPort ( GrafPtr newPort )
  323. {
  324.     dprintf ( "QTime::SetPort(%lx)", newPort );
  325.     
  326.     if ( GetParent() )
  327.         SetMovieGWorld ( GetParent()->mMovie, (CGrafPtr) mPort, nil );
  328. }
  329.                         
  330. //    ============================================================================================
  331.  
  332. PictureAnimatedIcon::PictureAnimatedIcon ( void* iconSuiteToReplace, PictureAnimatedIconResourceHandle picInfoH ) :
  333.     AnimatedIcon ( iconSuiteToReplace )
  334. {
  335.  
  336.     if ( (**picInfoH).signature == 'KSDC' && (**picInfoH).version == 1 )
  337.     {
  338.         mPictureH = (PicHandle) Get1Resource ( 'PICT', (**picInfoH).pictureResID );
  339.  
  340.         mPictureFlags = (**picInfoH).flags;
  341.         
  342.         if ( mPictureH && *mPictureH )
  343.         {
  344.             DetachResource ( (Handle) mPictureH );
  345.             
  346.             if ( HandleZone( (Handle) mPictureH ) != SystemZone () )
  347.             {    Handle h = NewHandleSys ( GetHandleSize ( (Handle) mPictureH ) );
  348.             
  349.                 if ( h && *h )
  350.                 {
  351.                     BlockMoveData ( *mPictureH, *h, GetHandleSize( h ) );
  352.                     DisposeHandle ( (Handle) mPictureH );
  353.                     mPictureH = (PicHandle) h;
  354.                 }
  355.             }    
  356.         }
  357.         else
  358.             mPictureH = nil;
  359.             
  360.     }
  361. }
  362.  
  363. PictureAnimatedIcon::~PictureAnimatedIcon ()
  364. {
  365.     if ( mPictureH )
  366.         DisposeHandle( (Handle) mPictureH );
  367.     mPictureH  = nil;
  368. }
  369.  
  370. //    ============================================================================================
  371.  
  372. PictureAnimatedIconOnScreen::PictureAnimatedIconOnScreen ( AnimatedIcon* animatedIcon, GrafPtr port, const Rect* rect, IconAlignmentType align, IconTransformType transform ) :
  373.     AnimatedIconOnScreen ( animatedIcon, port, rect, align, transform )
  374. {
  375. }
  376.  
  377. PictureAnimatedIconOnScreen::~PictureAnimatedIconOnScreen ( )
  378. {
  379. }
  380.  
  381. #define kParentRect 1
  382.                             
  383. OSErr PictureAnimatedIconOnScreen::Draw ( const Rect* rect, IconAlignmentType align, IconTransformType transform )
  384. {
  385.     mInvalidatedCount = 0;
  386.     
  387.     if ( GetParent() && GetParent()->mPictureH  )
  388.         if ( GetParent()->mPictureFlags & kParentRect  )
  389.         {
  390.             Rect myRect = (*(GetParent()->mPictureH))->picFrame;
  391.             OffsetRect(&myRect,
  392.                        ((rect->left + rect->right)>>1) - ((myRect.left + myRect.right)>>1),
  393.                        rect->bottom - myRect.bottom);
  394.             
  395.             DrawPicture ( GetParent()->mPictureH, &myRect );
  396.         }
  397.         else
  398.             DrawPicture ( GetParent()->mPictureH, rect );
  399.     
  400.     return noErr;
  401. }
  402.  
  403. //    ============================================================================================
  404.  
  405. SoundAnimatedIcon::SoundAnimatedIcon ( void* iconSuiteToReplace, SoundAnimatedIconResourceHandle soundInfoH ) :
  406.     AnimatedIcon ( iconSuiteToReplace )
  407. {
  408.  
  409.     if ( (**soundInfoH).signature == 'KSDC' && (**soundInfoH).version == 1 )
  410.     {
  411.         mSoundH = (SndListHandle) Get1Resource ( 'snd ', (**soundInfoH).soundResID );
  412.         mSoundFlags = (**soundInfoH).flags;
  413.         mMinTicksBetweenSounds = (**soundInfoH).minTimeBetweenSounds;
  414.         mMaxTicksBetweenSounds = (**soundInfoH).maxTimeBetweenSounds;
  415.         
  416.         if ( mSoundH && *mSoundH )
  417.         {
  418.             DetachResource ( (Handle) mSoundH );
  419.             
  420.             if ( HandleZone( (Handle) mSoundH ) != SystemZone () )
  421.             {    Handle h = NewHandleSys ( GetHandleSize ( (Handle) mSoundH ) );
  422.             
  423.                 if ( h && *h )
  424.                 {
  425.                     BlockMoveData ( *mSoundH, *h, GetHandleSize( h ) );
  426.                     DisposeHandle ( (Handle) mSoundH );
  427.                     mSoundH = (SndListHandle) h;
  428.                 }
  429.             }    
  430.         }
  431.         else
  432.             mSoundH = nil;
  433.             
  434.     }
  435. }
  436.  
  437. SoundAnimatedIcon::~SoundAnimatedIcon ()
  438. {
  439.     if ( mSoundH )
  440.         DisposeHandle( (Handle) mSoundH );
  441.     mSoundH  = nil;
  442. }
  443.  
  444. //    ============================================================================================
  445.  
  446. static unsigned long RandomBetween ( unsigned long min, unsigned long max )
  447. {
  448.     if (min > max)
  449.         return min;
  450.     else
  451.         return min + Random() % ( max - min );
  452. }
  453.  
  454. static unsigned long min ( unsigned long a, unsigned long b )
  455. {
  456.     return ( a < b ) ? a : b ;
  457. }
  458.  
  459. SoundAnimatedIconOnScreen::SoundAnimatedIconOnScreen ( AnimatedIcon* animatedIcon, GrafPtr port, const Rect* rect, IconAlignmentType align, IconTransformType transform ) :
  460.     AnimatedIconOnScreen ( animatedIcon, port, rect, align, transform )
  461. {
  462.     if ( SndNewChannel ( & mSoundChannel, 0, 0, nil ) != noErr )
  463.         mSoundChannel = nil;
  464.         
  465.     mNextTickToStartPlayingSound = TickCount() + RandomBetween ( 5, GetParent()->mMinTicksBetweenSounds );
  466. }
  467.  
  468. SoundAnimatedIconOnScreen::~SoundAnimatedIconOnScreen ( )
  469. {
  470.     if ( mSoundChannel )
  471.         SndDisposeChannel ( mSoundChannel, true );        
  472. }
  473.                             
  474. OSErr SoundAnimatedIconOnScreen::Draw ( const Rect* rect, IconAlignmentType align, IconTransformType transform )
  475. {
  476.     #pragma unused( rect, align, transform )
  477.     
  478.     mInvalidatedCount = 0;
  479.     
  480.     return errForceCallToOriginalPlotIcon;
  481. }
  482.  
  483. unsigned long SoundAnimatedIconOnScreen::Idle ()
  484. {
  485.     if (( mNextTickToStartPlayingSound > TickCount() ) &&
  486.         ( mNextTickToStartPlayingSound != ULONG_MAX ) && 
  487.         (GetParent()->mSoundFlags & kMouseTriger))
  488.     {
  489.         GrafPtr savePort;
  490.         Point mouse;
  491.         
  492.         ::GetPort ( & savePort );
  493.         
  494.         SetPort( GetPort() );
  495.         
  496.         GetMouse(&mouse);
  497.         if ( PtInRect( mouse, & GetRect() ) )
  498.             mNextTickToStartPlayingSound = 0;
  499.         
  500.         SetPort ( savePort );
  501.     }
  502.  
  503.     if ( mNextTickToStartPlayingSound < TickCount() )
  504.     {
  505.         HLock ( (Handle) GetParent()->GetSoundH() );
  506.         
  507.         SndPlay ( mSoundChannel, GetParent()->GetSoundH(), true );
  508.     
  509.         mNextTickToStartPlayingSound = ULONG_MAX;
  510.     }
  511.     else if ( mNextTickToStartPlayingSound == ULONG_MAX )
  512.     {    SCStatus    statusRec;
  513.     
  514.         OSErr err = SndChannelStatus ( mSoundChannel, sizeof( statusRec ), & statusRec );
  515.         
  516.         if ( err == noErr )
  517.         {
  518.             if ( statusRec.scChannelBusy == false )
  519.             {
  520.                 mNextTickToStartPlayingSound = TickCount() + RandomBetween ( GetParent()->mMinTicksBetweenSounds, GetParent()->mMaxTicksBetweenSounds );
  521.             
  522.                 HUnlock ( (Handle) GetParent()->GetSoundH() );
  523.             }
  524.         }
  525.     }
  526.  
  527.     return min ( 300, mNextTickToStartPlayingSound - TickCount() );
  528. }
  529.  
  530. //    ============================================================================================
  531.  
  532. VoiceAnimatedIcon::VoiceAnimatedIcon ( void* iconSuiteToReplace, VoiceAnimatedIconResourceHandle VoiceInfoH, FSSpec* spec ) :
  533.     AnimatedIcon ( iconSuiteToReplace )
  534. {
  535.  
  536.     if ( (**VoiceInfoH).signature == 'KSDC' && (**VoiceInfoH).version == 1 )
  537.     {
  538.         if ((**VoiceInfoH).VoiceResID)
  539.             mVoiceH = (Str255**) Get1Resource ( 'STR ', (**VoiceInfoH).VoiceResID );
  540.         else if (spec != nil)
  541.         {
  542.             mVoiceH = ( Str255** ) NewHandle(256);
  543.             BlockMoveData(spec->name, *mVoiceH, spec->name[0]+1);
  544.         }
  545.         else
  546.         {
  547.             mVoiceH = ( Str255** ) NewHandle(256);
  548.             BlockMoveData("\pNo File Name", *mVoiceH, 13);
  549.         }
  550.         mVoiceFlags = (**VoiceInfoH).flags;
  551.         mMinTicksBetweenVoice = (**VoiceInfoH).minTimeBetweenVoice;
  552.         mMaxTicksBetweenVoice = (**VoiceInfoH).maxTimeBetweenVoice;
  553.         
  554.         if ( mVoiceH && *mVoiceH )
  555.         {
  556.             DetachResource ( (Handle) mVoiceH );
  557.             
  558.             if ( HandleZone( (Handle) mVoiceH ) != SystemZone () )
  559.             {    Handle h = NewHandleSys ( GetHandleSize ( (Handle) mVoiceH ) );
  560.             
  561.                 if ( h && *h )
  562.                 {
  563.                     BlockMoveData ( *mVoiceH, *h, GetHandleSize( h ) );
  564.                     DisposeHandle ( (Handle) mVoiceH );
  565.                     mVoiceH = (Str255**) h;
  566.                 }
  567.             }    
  568.         }
  569.         else
  570.             mVoiceH = nil;
  571.             
  572.     }
  573. }
  574.  
  575. VoiceAnimatedIcon::~VoiceAnimatedIcon ()
  576. {
  577.     if ( mVoiceH )
  578.         DisposeHandle( (Handle) mVoiceH );
  579.     mVoiceH  = nil;
  580. }
  581.  
  582.  
  583. VoiceAnimatedIconOnScreen::VoiceAnimatedIconOnScreen ( AnimatedIcon* animatedIcon, GrafPtr port, const Rect* rect, IconAlignmentType align, IconTransformType transform ) :
  584.     AnimatedIconOnScreen ( animatedIcon, port, rect, align, transform )
  585. {
  586.  
  587.     if ( NewSpeechChannel ( nil, & mVoiceChannel ) != noErr )
  588.         mVoiceChannel = nil;
  589.         
  590.     mNextTickToStartPlayingVoice = TickCount() + RandomBetween ( 5, GetParent()->mMinTicksBetweenVoice );
  591. }
  592.  
  593. VoiceAnimatedIconOnScreen::~VoiceAnimatedIconOnScreen ( )
  594. {
  595.     if ( mVoiceChannel )
  596.         DisposeSpeechChannel ( mVoiceChannel );        
  597. }
  598.                             
  599. OSErr VoiceAnimatedIconOnScreen::Draw ( const Rect* rect, IconAlignmentType align, IconTransformType transform )
  600. {
  601.     #pragma unused( rect, align, transform )
  602.     
  603.     return errForceCallToOriginalPlotIcon;
  604. }
  605.  
  606. unsigned long VoiceAnimatedIconOnScreen::Idle ()
  607. {
  608.     if (( mNextTickToStartPlayingVoice > TickCount() ) &&
  609.         ( mNextTickToStartPlayingVoice != ULONG_MAX ) && 
  610.         (GetParent()->mVoiceFlags & kMouseTriger))
  611.     {
  612.         GrafPtr savePort;
  613.         Point mouse;
  614.         
  615.         ::GetPort ( & savePort );
  616.         
  617.         SetPort( GetPort() );
  618.         
  619.         GetMouse(&mouse);
  620.         if (PtInRect(mouse, &GetRect()))
  621.             mNextTickToStartPlayingVoice = 0;
  622.         
  623.         SetPort (savePort);
  624.     }
  625.  
  626.     if ( mNextTickToStartPlayingVoice < TickCount() )
  627.     {
  628.         HLock ( (Handle) GetParent()->GetVoiceH() );
  629.         
  630.         SpeakString ( (unsigned char *) *(GetParent()->GetVoiceH()));
  631.     
  632.         mNextTickToStartPlayingVoice = ULONG_MAX;
  633.     }
  634.     else if ( mNextTickToStartPlayingVoice == ULONG_MAX )
  635.     if ( 0 == SpeechBusySystemWide () )
  636.     {
  637.         mNextTickToStartPlayingVoice = TickCount() + RandomBetween ( GetParent()->mMinTicksBetweenVoice, GetParent()->mMaxTicksBetweenVoice );
  638.     
  639.         }
  640.  
  641.     return min ( 300, mNextTickToStartPlayingVoice - TickCount() );
  642. }
  643.  
  644. //    ============================================================================================
  645.